﻿using System;
using System.Collections.Generic;
using System.Text;
using Cn.Cellula.Biz.Port;
using Cn.Cellula.Model;
using System.Xml;
using System.Reflection;
using System.Web.UI.WebControls;
using Cn.Edwon.Web.Session;
using Cn.Cellula.Model.Security;
using Cn.Cellula.Model.Security.Power;
using Cn.Edwon.Web.Ac;
using Cn.Edwon.Web;
using Cn.Edwon.Spring;

namespace Cn.Cellula.Biz.Impl {
    class UserBiz : MyBizSupport, IUserBiz {
        private string GetCatalogPrefix(XmlNode n, string prefix) {
            string _prefix = "";
            n = n.ParentNode;
            while (n.Name != "root") {
                _prefix += prefix;
                n = n.ParentNode;
            }
            return _prefix;
        }
        #region Func 操作

        public IList<TSysFunctionEO> LoadFunctions(string parentKey) {
            String hql;
            if (String.IsNullOrEmpty(parentKey)) {
                hql = " from TSysFunctionEO eo where eo.ParentKey='' or eo.ParentKey is null ";
            } else {
                hql = " from TSysFunctionEO eo where eo.ParentKey='" + parentKey + "'";
            }
            return base.Find<TSysFunctionEO>(hql);
        }

        public string LoadFunctions2Json(ISessActor rActor,string parentKey) {
            try {
                XmlDocument doc = LoadFunction2XHtml(rActor, parentKey);
                XmlNode root = doc.DocumentElement;
                return LoadFunctions2Json(root);
            } catch(Exception ex) {
                log.Error(ex.Message);
                return "[]";
            }
        }

        public String LoadFunctions2Json(XmlNode node) {
            StringBuilder sb = new StringBuilder();
            String id, name, menuName, url, pattern, parentId,orgOpen;
            Int32 order = 0;
            if (node.Name == "root") {
                id = "root";
                name = "/";
                menuName = "";
                url = "#";
                pattern = "";
                orgOpen = "0";
                parentId = null;
            } else {
                id = node.Attributes["id"].Value;
                name = node.Attributes["name"].Value;
                menuName = node.Attributes["menu-name"].Value;
                url = node.Attributes["url"].Value;
                pattern = node.Attributes["pattern"].Value;
                parentId = node.Attributes["parent"].Value;
                orgOpen = node.Attributes["org-open"].Value;
                try {
                    order = Convert.ToInt32(node.Attributes["order"].Value);
                } catch { }
            }
            sb.Append("{");
            sb.Append("\"ParnetId\":\"" + parentId + "\"");
            sb.Append(",\"Id\":\"" + id + "\"");
            sb.Append(",\"Name\":\"" + name + "\"");
            sb.Append(",\"MenuName\":\"" + menuName + "\"");
            sb.Append(",\"Url\":\"" + url + "\"");
            sb.Append(",\"Pattern\":\"" + pattern + "\"");
            sb.Append(",\"Order\":\"" + order + "\"");
            sb.Append(",\"FlgOrgOpen\":\"" + orgOpen + "\"");
            sb.Append(",\"Children\":[");
            if (node.ChildNodes.Count > 0) {
                for (int i = 0; i < node.ChildNodes.Count; i++) {
                    if (i > 0)
                        sb.Append(",");
                    sb.Append(LoadFunctions2Json(node.ChildNodes[i]));
                }
            }
            sb.Append("]");
            sb.Append("}");
            return sb.ToString();
        }

        public XmlDocument LoadFunction2XHtml(ISessActor rActor,string parentKey) {
            String hql = "";
            String userKey = (rActor == null) ? "" : rActor.ID;
            if (BizConst.Admin.KEY == userKey) {//超级管理员，返回所有功能
                hql = " from TSysFunctionEO eo order by eo.OrderNumber desc,eo.MenuName ";
                IList<TSysFunctionEO> list = base.Find<TSysFunctionEO>(hql);
                //启动一个空的xmlDocument对象
                XmlDocument dom = new XmlDocument();
                dom.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\" ?><root></root>");
                XmlElement root = dom.DocumentElement;
                //将catalog全部装入Dom对象
                foreach (TSysFunctionEO eo in list) {
                    XmlElement node = dom.CreateElement("div");
                    node.SetAttribute("id", eo.FuncKey);
                    node.SetAttribute("layer", "0");
                    if (String.IsNullOrEmpty(eo.ParentKey)) {
                        node.SetAttribute("parent", "");
                    } else {
                        node.SetAttribute("parent", eo.ParentKey);
                    }
                    node.SetAttribute("name", eo.FuncName);
                    node.SetAttribute("url", eo.Url);
                    node.SetAttribute("menu-name", eo.MenuName);
                    node.SetAttribute("pattern", eo.MarkPattern);
                    node.SetAttribute("order", eo.OrderNumber + "");
                    node.SetAttribute("org-open", eo.FlgOrgOpen + "");
                    root.AppendChild(node);
                }
                //按照父子关系移动节点对象
                XmlNodeList nodes = root.ChildNodes;
                //Int32 _parentLayer = 0;
                foreach (TSysFunctionEO eo in list) {
                    if (String.IsNullOrEmpty(eo.ParentKey)) continue;
                    XmlNode n = root.SelectSingleNode("//div[@id='" + eo.FuncKey + "']");
                    XmlNode p = root.SelectSingleNode("//div[@id='" + eo.ParentKey + "']");
                    if (n != null && p != null) {
                        //_parentLayer = Convert.ToInt32(p.Attributes["layer"].Value.ToString());
                        //n.Attributes["layer"].Value = (_parentLayer+1)+"";
                        p.AppendChild(n);
                    }
                }
                return dom;
            } else {
                hql = " from VUserFunctionEO eo where eo.UserKey='" + userKey + "' order by eo.OrderNumber desc,eo.MenuName ";
                IList<VUserFunctionEO> list = base.Find<VUserFunctionEO>(hql);
                //启动一个空的xmlDocument对象
                XmlDocument dom = new XmlDocument();
                dom.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\" ?><root></root>");
                XmlElement root = dom.DocumentElement;
                //将catalog全部装入Dom对象
                foreach (VUserFunctionEO eo in list) {
                    XmlElement node = dom.CreateElement("div");
                    node.SetAttribute("id", eo.FuncKey);
                    node.SetAttribute("layer", "0");
                    if (String.IsNullOrEmpty(eo.ParentKey)) {
                        node.SetAttribute("parent", "");
                    } else {
                        node.SetAttribute("parent", eo.ParentKey);
                    }
                    node.SetAttribute("name", eo.FuncName);
                    node.SetAttribute("url", eo.Url);
                    node.SetAttribute("menu-name", eo.MenuName);
                    node.SetAttribute("pattern", eo.MarkPattern);
                    node.SetAttribute("order", eo.OrderNumber + "");
                    node.SetAttribute("org-open", eo.FlgOrgOpen + "");
                    root.AppendChild(node);
                }
                //按照父子关系移动节点对象
                XmlNodeList nodes = root.ChildNodes;
                //Int32 _parentLayer = 0;
                foreach (VUserFunctionEO eo in list) {
                    if (String.IsNullOrEmpty(eo.ParentKey)) continue;
                    XmlNode n = root.SelectSingleNode("//div[@id='" + eo.FuncKey + "']");
                    XmlNode p = root.SelectSingleNode("//div[@id='" + eo.ParentKey + "']");
                    if (n != null && p != null) {
                        //_parentLayer = Convert.ToInt32(p.Attributes["layer"].Value.ToString());
                        //n.Attributes["layer"].Value = (_parentLayer+1)+"";
                        p.AppendChild(n);
                    } else {
                        n.ParentNode.RemoveChild(n);
                    }
                }
                return dom;
            }
        }

        public void DeleteFunctions(string[] rKeys) {
            IList<TSysFunctionEO> list = null;
            foreach (String k in rKeys) {
                String hql = "from TSysFunctionEO eo where eo.ParentKey='"+k+"' ";
                list = base.Find<TSysFunctionEO>(hql);
                if (list != null && list.Count>0) {
                    throw new Exception("具有子节点的项(" + list[0].FuncName + ")无法被删除");
                }
                base.Delete<TSysFunctionEO>(k);
                DeleteRoleFunctionByFunc(k);
            }
        }

        public IList<ListItem> LoadFunc2ListItem(ISessActor rActor,string rPrefix, string rSelfKey, bool rSelected) {
            XmlDocument doc = this.LoadFunction2XHtml(rActor, null);
            if (!String.IsNullOrEmpty(rSelfKey)) {
                XmlNode _selfNode = doc.DocumentElement.SelectSingleNode("//div[@id='" + rSelfKey + "']");
                if (_selfNode != null) {
                    _selfNode.ParentNode.RemoveChild(_selfNode);
                }
            }
            XmlNodeList nodes = doc.SelectNodes("//div");
            IList<ListItem> list = new List<ListItem>();
            if (!rSelected)
                list.Add(new ListItem("", ""));
            foreach (XmlElement n in nodes) {
                ListItem eo = new ListItem();
                eo.Value = n.Attributes["id"].Value;
                eo.Text = GetCatalogPrefix(n, rPrefix) + n.Attributes["menu-name"].Value;
                list.Add(eo);
            }
            return list;
        }

        public string LoadFunctions2JskitMenuXml(ISessActor rActor, String parentKey) {
            String hql = "";
            String userKey = (rActor == null) ? "" : rActor.ID;
            XmlDocument dom = new XmlDocument();
            dom.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\" ?><root></root>");
            XmlElement root = dom.DocumentElement;
            root.SetAttribute("id", "root");
            String pk = Guid.NewGuid().ToString();
            if (BizConst.Admin.KEY == userKey) {//超级管理员，返回所有功能
                hql = " from TSysFunctionEO eo order by eo.OrderNumber desc,eo.MenuName ";
                IList<TSysFunctionEO> list = base.Find<TSysFunctionEO>(hql);
                //启动一个空的xmlDocument对象
                //将catalog全部装入Dom对象
                foreach (TSysFunctionEO eo in list) {
                    if (String.IsNullOrEmpty(eo.MenuName)) continue;
                    XmlElement node = dom.CreateElement("div");
                    node.SetAttribute("type", "jmnode");
                    node.SetAttribute("id", pk + eo.FuncKey);
                    node.SetAttribute("target", "_self");
                    if (String.IsNullOrEmpty(eo.ParentKey)) {
                        node.SetAttribute("css", "jskitmenu_item_f");
                    } else {
                        node.SetAttribute("css", "jskitmenu_item");
                    }
                    node.SetAttribute("url", eo.Url);
                    node.SetAttribute("name", eo.MenuName);
                    root.AppendChild(node);
                    int direct = GetNodeDirection(node);
                    node.SetAttribute("direction", direct + "");
                    node.SetAttribute("location", GetNodeLocation(direct) + "");
                    //获取菜单的层次

                }
                //按照父子关系移动节点对象
                XmlNodeList nodes = root.ChildNodes;
                //Int32 _parentLayer = 0;
                foreach (TSysFunctionEO eo in list) {
                    if (String.IsNullOrEmpty(eo.ParentKey)) continue;
                    XmlNode n = root.SelectSingleNode("//div[@id='" + pk + eo.FuncKey + "']");
                    if (n == null) continue;
                    XmlNode p = root.SelectSingleNode("//div[@id='" + pk + eo.ParentKey + "']");
                    if (p != null) {
                        p.AppendChild(n);
                    } else if(n.ParentNode!=null) {
                        n.ParentNode.RemoveChild(n);
                    }
                }
                return dom.InnerXml;
            } else {
                hql = " from VUserFunctionEO eo where eo.UserKey='" + userKey + "' order by eo.OrderNumber desc,eo.MenuName ";
                IList<VUserFunctionEO> list = base.Find<VUserFunctionEO>(hql);
                //将catalog全部装入Dom对象
                foreach (VUserFunctionEO eo in list) {
                    if (String.IsNullOrEmpty(eo.MenuName)) continue;
                    XmlElement node = dom.CreateElement("div");
                    node.SetAttribute("type", "jmnode");
                    node.SetAttribute("id", eo.FuncKey);
                    node.SetAttribute("target", "_self");
                    if (String.IsNullOrEmpty(eo.ParentKey)) {
                        node.SetAttribute("css", "jskitmenu_item_f");
                    } else {
                        node.SetAttribute("css", "jskitmenu_item");
                    }
                    node.SetAttribute("url", eo.Url);
                    node.SetAttribute("name", eo.MenuName);
                    root.AppendChild(node);
                    int direct = GetNodeDirection(node);
                    node.SetAttribute("direction", direct + "");
                    node.SetAttribute("location", GetNodeLocation(direct) + "");
                }
                //按照父子关系移动节点对象
                XmlNodeList nodes = root.ChildNodes;
                //Int32 _parentLayer = 0;
                foreach (VUserFunctionEO eo in list) {
                    if (String.IsNullOrEmpty(eo.ParentKey)) continue;
                    XmlNode n = root.SelectSingleNode("//div[@id='" + eo.FuncKey + "']");
                    if (n == null) continue;
                    XmlNode p = root.SelectSingleNode("//div[@id='" + eo.ParentKey + "']");
                    if (p != null) {
                        //_parentLayer = Convert.ToInt32(p.Attributes["layer"].Value.ToString());
                        //n.Attributes["layer"].Value = (_parentLayer+1)+"";
                        p.AppendChild(n);
                    } else if (n.ParentNode != null) {
                        n.ParentNode.RemoveChild(n);
                    }
                }
            }
            return dom.InnerXml;
        }

        #endregion
        #region Role 操作
        public IList<TSysRoleEO> LoadAllRoles(Int32? rActorRoleLevel) {
            String hql = "from TSysRoleEO eo where eo.RoleKey<>'" + BizConst.Admin.ROLE_KEY + "' ";
            hql += " and eo.RoleKey<>'" + BizConst.Guest.ROLE_KEY + " ' ";
            if (rActorRoleLevel != null) {
                hql += " and eo.RoleLevel<=" + rActorRoleLevel;
            } else {
                log.Debug("Role Level Lost,Load Roles failed");
                return new List<TSysRoleEO>();
            }
            hql += " order by eo.RoleLevel desc ";
            return base.Find<TSysRoleEO>(hql);
        }
        public void DeleteRoles(IList<String> rKeys) {
            foreach (String k in rKeys) {
                base.Delete<TSysRoleEO>(k);
                DeleteRoleFunctionByRole(k);
            }
        }

        public void DeleteRoleFunctionByRole(String rRoleKey) {
            String hql = "from TSysRoleFunctionEO eo where eo.RoleKey='" + rRoleKey + "' ";
            base.Delete(hql);
        }

        public void DeleteRoleFunctionByFunc(string rFuncKey) {
            String hql = "from TSysRoleFunctionEO eo where eo.FunctionKey='" + rFuncKey + "' ";
            base.Delete(hql);
        }

        public IList<TSysRoleFunctionEO> LoadRfByRole(string rRoleKey) {
            String hql = "from TSysRoleFunctionEO eo where eo.RoleKey='" + rRoleKey + "' ";
            return base.Find<TSysRoleFunctionEO>(hql);
        }

        public IList<VUserFunctionEO> LoadFuncByUser(String rUserKey) {
            String hql = "from VUserFunctionEO eo where eo.UserKey='" + rUserKey + "' ";
            return base.Find<VUserFunctionEO>(hql);
        }
        public void BindFunc2Role(string[] rFuncs, string rRoleKey) {
            DeleteRoleFunctionByRole(rRoleKey);
            foreach (String k in rFuncs) {
                TSysRoleFunctionEO eo = new TSysRoleFunctionEO();
                eo.RoleKey = rRoleKey;
                eo.FunctionKey = k;
                base.Save<TSysRoleFunctionEO>(eo);
            }
        }
        public Boolean IfRoleInUse(String rRoleKey) {
            //角色绑定了用户
            String hql = "from TSysUserEO eo where eo.RoleKey='" + rRoleKey + "' ";
            IList<TSysUserEO> list = base.Find<TSysUserEO>(hql);
            if (list != null && list.Count > 0) return true;
            //角色绑定了对象
            hql = " from TSysPowerEO eo where eo.RoleKey='" + rRoleKey + "' ";
            IList<TSysPowerEO> list2 = base.Find<TSysPowerEO>(hql);
            if (list2 != null && list2.Count > 0) return true;
            return false;
        }
        #endregion
        #region User 操作

        public Boolean IfUserNoExist(String rUserNO, String rUserKey) {
            String hql = "from TSysUserEO eo where eo.UserNo='" + rUserNO + "' ";
            if (rUserKey != null) {
                hql += " and eo.UserKey<>'" + rUserKey + "'";
            }
            IList<TSysUserEO> list = base.Find<TSysUserEO>(hql);
            return (list != null && list.Count > 0);
        }
        public void DeleteUsers(IList<String> rKeys) {
            foreach (String k in rKeys) {
                if (k == BizConst.Admin.KEY) continue;
                base.Delete<TSysUserEO>(k);
            }
        }

        public Boolean IfLoginNameExists(string rLoginName,String rUserKey) {
            String hql = "from TSysUserEO eo where eo.LoginName='"+rLoginName+"' ";
            if (rUserKey != null) {
                hql += " and eo.UserKey<>'" + rUserKey + "'";
            }
            IList<TSysUserEO> list = base.Find<TSysUserEO>(hql);
            return (list != null && list.Count > 0);
        }

        public Boolean IfEmailExists(string rEmail, String rUserKey) {
            String hql = "from TSysUserEO eo where eo.Email='" + rEmail + "' ";
            if (rUserKey != null) {
                hql += " and eo.UserKey<>'" + rUserKey + "'";
            }
            IList<TSysUserEO> list = base.Find<TSysUserEO>(hql);
            return (list != null && list.Count > 0);
        }
        public Boolean IfUserNameExists(string rUserName, String rUserKey) {
            String hql = "from TSysUserEO eo where eo.UserName='" + rUserName + "' ";
            if (rUserKey != null) {
                hql += " and eo.UserKey<>'" + rUserKey + "'";
            }
            IList<TSysUserEO> list = base.Find<TSysUserEO>(hql);
            return (list != null && list.Count > 0);
        }
        public int ChangePassword(String rUserKey, string rOldPwd, string rNewPwd) {
            if (rOldPwd == rNewPwd) {
                return 0;
            }
            try {
                TSysUserEO eo = base.Load<TSysUserEO>(rUserKey);
                if (eo.Password != rOldPwd) {
                    return 1;
                }
                eo.Password = rNewPwd;
                base.Update<TSysUserEO>(eo);
                return 0;
            } catch (Exception ex) {
                log.Error(ex.Message);
                return 2;
            }
        }
        public int ResetPassword(String rUserKey, String rNewPwd) {
            try {
                TSysUserEO eo = base.Load<TSysUserEO>(rUserKey);
                eo.Password = rNewPwd;
                base.Update<TSysUserEO>(eo);
                return 0;
            } catch (Exception ex) {
                log.Error(ex.Message);
                return 2;
            }
        }
        public VSysUserEO Login(String rLoginNameProperty,string rLoginName, string rMd5Pwd) {
            String hql = "from VSysUserEO eo where eo." + rLoginNameProperty + "='" + rLoginName + "' and eo.Password='" + rMd5Pwd + "'";
            IList<VSysUserEO> list = base.Find<VSysUserEO>(hql);
            return (list != null && list.Count > 0) ? list[0] : null;
        }
        public VSysUserEO Login(String rUserKey, String rMd5Pwd) {
            String hql = "from VSysUserEO eo where eo.UserKey='" + rUserKey + "' and eo.Password='" + rMd5Pwd + "'";
            IList<VSysUserEO> list = base.Find<VSysUserEO>(hql);
            return (list != null && list.Count > 0) ? list[0] : null;
        }

        public IList<VSysUserEO> LoadAllUsers() {
            String hql = "from VSysUserEO eo where eo.IsUnlistable=0 order by eo.UserName ";
            return base.Find<VSysUserEO>(hql);
        }
        public string GenerateUserNo() {
            IList<VUserNoMaxEO> list = base.LoadAll<VUserNoMaxEO>();
            if (list != null && list.Count == 1) {
                Int32 no = Convert.ToInt32(list[0].UserNo);
                return (no + 1) + "";
            } else {
                return "10000";
            }
        }
        public IList<VSysUserEO> LoadLowerUser(String rUserKey,UserPower rPower,Boolean rHasSelf) {
            //检查用户的部门
            //获得所有的子部门
            //IDeptBiz deptBiz = BizFactory.Get<IDeptBiz>();
            //IList<String> depts = deptBiz.LoadDescendantsKeys(null, rPower.DeptKey);
            IList<VSysUserEO> list = new List<VSysUserEO>();
            String hql = "from VSysUserEO eo where eo.DeptKey is not null";
            hql += " and eo.RoleLevel<" + rPower.RoleLevel;
            hql += " and eo.ActivatedFlg=1 ";
            hql += " and (eo.DeptKey='" + rPower.DeptKey + "'";
            hql += " or eo.DeptLevel<" + rPower.DeptLevel;
            hql += " )";
            hql += " order by eo.UserName";
            list = base.Find<VSysUserEO>(hql);
            return list;
        }
        #endregion

        #region Power 操作
        public void BindPower(String rObjectKey, String rVisiableRoleKey, String rEditableRoleKey,String rDeptKey,String rOperator) {
            TSysPowerEO eo;
            try {
                eo = base.Load<TSysPowerEO>(rObjectKey);
            } catch {
                eo = null;
            }
            if (eo == null) {
                eo = new TSysPowerEO();
                eo.LastDt = DateTime.Now;
                eo.ObjectKey = rObjectKey;
                eo.Operator = rOperator;
                eo.VisiableRoleKey = rVisiableRoleKey;
                eo.EditableRoleKey = rEditableRoleKey;
                eo.DeptKey = rDeptKey;
                base.Save<TSysPowerEO>(eo);
            } else {
                eo.LastDt = DateTime.Now;
                eo.Operator = rOperator;
                eo.VisiableRoleKey = rVisiableRoleKey;
                eo.EditableRoleKey = rEditableRoleKey;
                eo.DeptKey = rDeptKey;
                base.Update<TSysPowerEO>(eo);
            }

        }

 
        #endregion
     
        #region 内部函数
        private int GetNodeDirection(XmlElement rNode) {
            int layers = 1;
            XmlNode node = (XmlNode)rNode;
            while (node.Name != "root") {
                node = node.ParentNode;
                layers++;
            }
            return (layers % 2 == 0) ? 2 : 1;
        }
        private int GetNodeLocation(int direction) {
            return (direction==1) ? 2 : 3;
        }

        #endregion

    }
}
